/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.engine.runtime.jxls;

import cn.easyplatform.EntityNotFoundException;
import cn.easyplatform.entities.beans.LogicBean;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.support.scripting.RhinoScriptable;
import cn.easyplatform.support.scripting.ScriptUtils;
import cn.easyplatform.type.EntityType;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.jxls.common.AreaListener;
import org.jxls.common.CellRef;
import org.jxls.common.Context;
import org.jxls.transform.poi.PoiTransformer;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Script;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Author: <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @Description:
 * @Since: 2.0.0 <br/>
 * @Date: Created in 2019/10/28 10:49
 * @Modified By:
 */
class JxlsAreaListener implements AreaListener {

    private static Logger log = LoggerFactory.getLogger(JxlsAreaListener.class);

    private RhinoScriptable scope;

    private Script scriptEval;

    private CommandContext cc;

    private PoiTransformer transformer;

    JxlsAreaListener(CommandContext cc, PoiTransformer transformer, String event) {
        this.transformer = transformer;
        this.cc = cc;
        org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();
        try {
            cx.setOptimizationLevel(9);
            this.scope = new RhinoScriptable();
            this.scope.initStandardObjects(cx, false);
            StringBuilder sb = new StringBuilder();
            sb.append("importPackage(Packages.org.apache.poi.ss.usermodel);");
            if (event.matches("\\w")) {
                LogicBean lb = cc.getEntity(event);
                if (lb == null)
                    throw new EntityNotFoundException(
                            EntityType.LOGIC.getName(), event);
                sb.append(lb.getContent());
            } else
                sb.append(event);
            if (log.isInfoEnabled())
                log.info("execute->{}", sb);
            scriptEval = cx.compileString(sb.toString(), "", 1, null);
        } catch (RhinoException ex) {
            throw ScriptUtils.handleScriptException(cc, ex);
        } finally {
            org.mozilla.javascript.Context.exit();
        }
    }

    @Override
    public void beforeApplyAtCell(CellRef cellRef, Context context) {
    }

    @Override
    public void afterApplyAtCell(CellRef cellRef, Context context) {
    }

    @Override
    public void beforeTransformCell(CellRef srcCell, CellRef targetCell, Context context) {
    }

    @Override
    public void afterTransformCell(CellRef srcCell, CellRef targetCell, Context context) {
        org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();
        try {
            cx.setOptimizationLevel(9);
            scope.putAll(context.toMap());
            Workbook workbook = transformer.getWorkbook();
            Sheet sheet = workbook.getSheet(targetCell.getSheetName());
            Cell cell = sheet.getRow(targetCell.getRow()).getCell(targetCell.getCol());
            scope.setVariable("workbook", workbook);
            scope.setVariable("sheet", sheet);
            scope.setVariable("$source", srcCell);//参考getCell()方法
            scope.setVariable("$", cell);
            scriptEval.exec(cx, scope);
        } catch (RhinoException ex) {
            throw ScriptUtils.handleScriptException(cc, ex);
        } finally {
            org.mozilla.javascript.Context.exit();
        }
    }
}
